<script lang="tsx">
  import {compile, defineComponent, h, ref} from 'vue';
  import {RouteMeta, RouteRecordRaw, useRoute, useRouter} from 'vue-router';
  import {listenerRouteChange} from '@/utils/route-listener';
  import useMenuTree from './use-menu-tree';
  import {openWindow, regexUrl} from '@/utils';

  export default defineComponent({
    emit: ['collapse'],
    setup() {

      const router = useRouter();
      const route = useRoute();
      const openKeys = ref<string[]>([]);
      const selectedKey = ref<string[]>([]);
      const {menuTree} = useMenuTree();

      const goto = (item: RouteRecordRaw) => {
        // Open external link
        if (regexUrl.test(item.path)) {
          openWindow(item.path);
          selectedKey.value = [item.name as string];
          return;
        }
        // Eliminate external link side effects
        selectedKey.value = [item.name as string];
        const {hideInMenu, activeMenu} = item.meta as RouteMeta;
        if (route.name === item.name && !hideInMenu && !activeMenu) {
          return;
        }
        // Trigger router change
        router.push({
          name: item.name,
        });
      };
      const findMenuOpenKeys = (name: string) => {
        const result: string[] = [];
        let isFind = false;
        const backtrack = (
            item: RouteRecordRaw,
            keys: string[],
            target: string
        ) => {
          if (item.name === target) {
            isFind = true;
            result.push(...keys, item.name as string);
            return;
          }
          if (item.children?.length) {
            item.children.forEach((el) => {
              backtrack(el, [...keys], target);
            });
          }
        };
        menuTree.value.forEach((el: RouteRecordRaw) => {
          if (isFind) return; // Performance optimization
          backtrack(el, [el.name as string], name);
        });
        return result;
      };
      // 控制刷新后的菜单选择
      listenerRouteChange((newRoute) => {
        const {requiresAuth, activeMenu, hideInMenu} = newRoute.meta;
        console.warn(requiresAuth, activeMenu, hideInMenu)
        if ((!hideInMenu || activeMenu)) {
          const menuOpenKeys = findMenuOpenKeys(
              (activeMenu || newRoute.name) as string
          );

          const keySet = new Set([...menuOpenKeys, ...openKeys.value]);
          openKeys.value = [...keySet];

          selectedKey.value = [
            activeMenu || menuOpenKeys[menuOpenKeys.length - 1],
          ];
        }
      }, true);

      const renderSubMenu = () => {
        function travel(_route: RouteRecordRaw[] | undefined, nodes = []) {
          if (_route) {
            _route.filter((element) => {
              return !element?.meta?.hideInMenu;
            }).forEach((element) => {
              // This is demo, modify nodes as needed
              const icon = element?.meta?.icon
                  ? () => h(compile(`<${element?.meta?.icon}/>`))
                  : null;
              const node =
                  element?.children && element?.children.length !== 0 ? (
                      <a-sub-menu
                          key={element?.name}
                          v-slots={{
                            icon,
                            title: () => h(compile(element?.meta?.locale || '')),
                          }}
                      >
                        {travel(element?.children)}
                      </a-sub-menu>
                  ) : (
                      <a-menu-item
                          key={element?.name}
                          v-slots={{icon}}
                          onClick={() => goto(element)}
                      >
                        {element?.meta?.locale || ''}
                      </a-menu-item>
                  );
              nodes.push(node as never);
            });
          }
          return nodes;
        }

        return travel(menuTree.value);
      };

      return () => (
          <a-menu
              v-model:open-keys={openKeys.value}
              mode="horizontal"
              selected-keys={selectedKey.value}
              style="width: 600px"
          >
            {renderSubMenu()}
          </a-menu>
      );
    }
  });
</script>

<style lang="less" scoped>
  :deep(.arco-menu-inner) {
    .arco-menu-inline-header {
      display: flex;
      align-items: center;
    }

    .arco-icon {
      &:not(.arco-icon-down) {
        font-size: 18px;
      }
    }
  }
</style>
